package com.hb.trade.api.routine.controller.center.sys;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.hb.core.pojo.center.au.entity.Role;
import com.hb.core.pojo.center.au.entity.User;
import com.hb.core.pojo.center.sys.dto.MenuResourceDTO;
import com.hb.core.pojo.center.sys.entity.MenuResource;
import com.hb.core.pojo.enums.RoleSignEnum;
import com.hb.core.pojo.enums.RoleTypeEnum;
import com.hb.core.pojo.enums.UserStatusEnum;
import com.hb.core.pojo.parent.MPCommonEntity;
import com.hb.trade.api.routine.util.CommonUtil;
import com.hb.trade.client.center.MenuResourceClient;
import com.hb.trade.client.center.RoleClient;
import com.hb.trade.client.center.UserClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.auth.shiro.util.ShiroUtil;
import org.fzzn.core.model.enums.UserTypeEnum;
import org.fzzn.core.model.msg.Message;
import org.fzzn.core.model.msg.ResponseDto;
import org.fzzn.core.util.Enums;
import org.fzzn.core.util.ResultUtil;
import org.fzzn.core.util.encrypt.PinyinUtil;
import org.fzzn.core.web.anno.Version;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 目录资源信息表 前端控制器
 *
 * @author zjk
 * @since 2021-01-11
 */
@RestController
@Slf4j
@Version(1.0)
@Api(tags = {"系统左侧导航菜单"})
@RequestMapping("/{version}")
public class ApiMenuResourceController {

    protected final UserClient userClient;
    protected final MenuResourceClient menuResourceClient;
    protected final RoleClient roleClient;

    public ApiMenuResourceController(UserClient userClient,
                                     RoleClient roleClient,
                                     MenuResourceClient menuResourceClient) {
        this.userClient = userClient;
        this.menuResourceClient = menuResourceClient;
        this.roleClient = roleClient;
    }

    @ApiOperation(value = "新增一个菜单", notes = "新增一个菜单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "parentId", value = "父级ID", dataTypeClass = Long.class),
            @ApiImplicitParam(name = "resName", value = "资源名称", dataTypeClass = String.class, required = true),
            @ApiImplicitParam(name = "targetPath", value = "跳转路由", dataTypeClass = String.class),
            @ApiImplicitParam(name = "pageUrl", value = "页面路径", dataTypeClass = String.class),
            @ApiImplicitParam(name = "icon", value = "图标", dataTypeClass = String.class),
            @ApiImplicitParam(name = "resType", value = "类型(1: 菜单, 2: 按钮)", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "sortNum", value = "排序号", dataTypeClass = Integer.class)
    })
    @PostMapping("/menuResource/addMenu")
    public ResponseDto addMenu(@RequestBody MenuResourceDTO menuDto) {
        String resName = menuDto.getResName();
        if (StrUtil.isEmpty(resName)) {
            return ResultUtil.fail("名称不能为空");
        }

        // 设置权限代码
        menuDto.setAuthCode(PinyinUtil.getPingYin(resName));

        // 设置菜单层级和父级ID
        Long parentId = menuDto.getParentId();
        if (parentId == null || NumberUtil.equals(parentId, 0)) {
            menuDto.setParentId(0L);
            menuDto.setLevel(1);
        } else {
            Message<MenuResource> parentMsg = menuResourceClient.getMenu(parentId);
            if (parentMsg.isSuccess()) {
                menuDto.setLevel(parentMsg.getData().getLevel() + 1);
            } else {
                return ResultUtil.fail("未能获取到指定的父级菜单信息");
            }
        }

        // 保存
        menuDto.buildBaseData(1, ShiroUtil.getUserEntity().getUsername());
        Message<Boolean> message = menuResourceClient.addMenu(menuDto);
        return ResultUtil.msg(message);
    }

    @ApiOperation(value = "修改菜单信息", notes = "修改菜单信息")
    @PostMapping("/menuResource/updateMenuResource")
    public ResponseDto updateMenuResource(@RequestBody MenuResourceDTO menuResource) {
        menuResource.buildBaseData(2, ShiroUtil.getUsername());
        Message<Boolean> message = menuResourceClient.updateMenuResource(menuResource);
        return ResultUtil.msg(message);
    }

    @ApiOperation(value = "删除一个菜单以及子集菜单", notes = "删除一个菜单以及子集菜单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "菜单ID", dataTypeClass = Long.class)
    })
    @PostMapping("/menuResource/deleteMenuResource")
    public ResponseDto deleteMenuResource(@RequestBody MenuResourceDTO menuResource) {
        Message<Boolean> message = menuResourceClient.removeMenu(menuResource.getId());
        return ResultUtil.msg(message);
    }

    @ApiOperation(value = "菜单维护列表信息", notes = "菜单维护列表信息")
    @PostMapping("/menuResource/listTrees")
    public ResponseDto listTrees(@RequestBody MenuResourceDTO menuResource) {
        // * 维护菜单不需要查询对应用户或角色的信息 * //
        menuResource.setRoleId(null);
        menuResource.setUserId(null);
        menuResource.setRoleSign(null);

        Message<List<MenuResourceDTO>> listMessage = menuResourceClient.listTrees(menuResource);
        if (listMessage.isSuccess()) {
            JSONArray menuTree = CommonUtil.getMenuTree(listMessage.getData());
            return ResultUtil.msg(true, menuTree);
        }
        return ResultUtil.FAIL;
    }

    @ApiOperation(value = "当前用户拥有的菜单列表", notes = "当前用户拥有的菜单列表(左侧导航栏用, 带按钮权限)")
/*    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleSign", value = "用户角色标识", dataTypeClass = Long.class, required = true)
    })*/
    @PostMapping("/menuResource/listTreesWithAuth")
    public ResponseDto<?> listTreesWithAuth(@RequestBody MenuResourceDTO menuResource) {
        // 从token中获取roleSign
        JSONObject extInfo = ShiroUtil.getExtInfo();
        Integer roleSign = extInfo.getInt("roleSign");

        // 获取当前登录用户信息
        Long userId = ShiroUtil.getUserId();
        Message<User> userMessage = userClient.getByUserId(userId);

        if (userMessage.isSuccess() && userMessage.getData() != null) {
            User userData = userMessage.getData();
            // 如果是超级管理员
            if (Enums.equals(UserTypeEnum.SUPER_ADMIN, userData.getUserType())) {
                // 返回全部菜单
                return listTrees(menuResource);
            }
            // 如果是未审核代理机构
            if ((userData.getUserStatus().equals(UserStatusEnum.DETAILED.getCode()) || userData.getUserStatus().equals(UserStatusEnum.REJECT.getCode()))) {
//                RoleTypeEnum roleTypeEnum = Enums.of(RoleTypeEnum.class,RoleTypeEnum.UN_CHECKED_AGENCY.getCode()) ;
//                Message<Role> roleMessage = roleClient.getRoleByRoleType(roleTypeEnum);
                roleSign = RoleTypeEnum.UN_CHECKED_AGENCY.getCode();
                MenuResourceDTO menuQuery = new MenuResourceDTO();
                // 临时方案，需要改成roleSign查询角色方式
                menuQuery.setRoleId(1506899590577774592L);
                Message<List<MenuResourceDTO>> listMessage = menuResourceClient.listTrees(menuQuery);
                if (listMessage.isSuccess()) {
                    JSONArray menuTree = CommonUtil.getMenuTree(listMessage.getData());
                    return ResultUtil.msg(true, menuTree);
                }
            }
        }

        // 系统用户登录时没有招投标角色
        MenuResourceDTO menuQuery = new MenuResourceDTO();

        if (roleSign == null) {
            return ResultUtil.fail("登录信息不完整, 无法获取菜单信息");
        }
        menuQuery.setRoleSign(roleSign);

        // 获取当前登录用户ID
        menuQuery.setUserId(userId);

        Message<List<MenuResourceDTO>> listMessage = menuResourceClient.listTrees(menuQuery);
        if (listMessage.isSuccess()) {
            JSONArray menuTree = CommonUtil.getMenuTree(listMessage.getData());
            return ResultUtil.msg(true, menuTree);
        }
        return ResultUtil.FAIL;
    }

    @ApiOperation(value = "获取指定角色的菜单权限列表", notes = "获取指定角色的菜单权限列表(树形结构)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", dataTypeClass = Long.class, required = true)
    })
    @PostMapping("/menuResource/listAllByRole")
    public ResponseDto<?> listAllByRole(@RequestBody MenuResourceDTO menuResource) {
        MenuResourceDTO menuQuery = new MenuResourceDTO();
        menuQuery.setRoleId(menuResource.getRoleId());

        Message<List<MenuResourceDTO>> listMessage = menuResourceClient.listTrees(menuQuery);
        if (listMessage.isSuccess()) {
            JSONArray menuTree = CommonUtil.getMenuTree(listMessage.getData());
            return ResultUtil.msg(true, menuTree);
        }
        return ResultUtil.FAIL;
    }

    /**
     * 获取当前登录用户和指定角色所能分配的权限合集
     *
     * @param menuResource
     * @return
     */
    @ApiOperation(value = "获取当前登录用户和指定角色所能分配的权限合集", notes = "获取当前登录用户和指定角色所能分配的权限合集(树形结构)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", dataTypeClass = Long.class, required = true)
    })
    @PostMapping("/menuResource/currentWithRoleId")
    public ResponseDto<?> currentWithRoleId(@RequestBody MenuResourceDTO menuResource) {
        Long userId = ShiroUtil.getUserId();

        Message<List<MenuResourceDTO>> menuMsg = menuResourceClient.currentWithRoleId(userId, menuResource.getRoleId());
        if (menuMsg.isSuccess()) {
            JSONArray menuTree = CommonUtil.getMenuTree(menuMsg.getData());
            return ResultUtil.msg(true, menuTree);
        }
        return ResultUtil.FAIL;
    }

    /**
     * 获取指定角色已拥有的权限集合
     *
     * @param menuResource
     * @return
     */
    @ApiOperation(value = "获取指定角色已拥有的权限集合", notes = "获取指定角色已拥有的权限集合(树形结构, roleId可以为null, 支持新增角色时的获取)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色ID", dataTypeClass = Long.class)
    })
    @PostMapping("/menuResource/authByRoleId")
    public ResponseDto<?> authByRoleId(@RequestBody MenuResourceDTO menuResource) {
        Message<List<MenuResourceDTO>> menuMsg = menuResourceClient.authByRoleId(menuResource.getRoleId());
        if (menuMsg.isSuccess()) {
            List<MenuResourceDTO> data = menuMsg.getData();
            List<Long> menuIds = CollUtil.map(data, MPCommonEntity::getId, true);
            return ResultUtil.msg(true, menuIds);
        }
        return ResultUtil.FAIL;
    }
}
